(function() {


/**
 * A simple model for creating file-attachment only review requests.
 *
 * Model Attributes:
 *     repository (RB.Repository):
 *         The associated repository (always ``null``).
 */
const FilesOnlyPreCommitModel = Backbone.Model.extend({
    defaults: _.defaults({
        repository: null,
    }),
});


/**
 * A simple view for creating file-attachment only review requests.
 */
const FilesOnlyPreCommitView = Backbone.View.extend({
    className: 'files-only',

    template: _.template(dedent`
        <p><%- description %></p>
        <input type="submit" class="primary large" id="files-only-create"
               value="<%- buttonText %>" />
    `),

    events: {
        'click #files-only-create': '_onCreateClicked',
    },

    /**
     * Render the view.
     *
     * Returns:
     *     FilesOnlyPreCommitView:
     *     This object, for chaining.
     */
    render() {
        this.$el.html(this.template({
            description: gettext('You won\'t be able to add any diffs to this review request. The review request will only be usable for reviewing graphics, screenshots and file attachments.'),
            buttonText: gettext('Create Review Request'),
        }));

        return this;
    },

    /**
     * Callback for when the "Create Review Request" button is clicked.
     *
     * Creates a review request with the given localSitePrefix and nothing else,
     * and redirects the browser to it.
     *
     * Args:
     *     ev (Event):
     *         The click event.
     */
    async _onCreateClicked(ev) {
        ev.preventDefault();
        ev.stopPropagation();

        const repository = this.model.get('repository');
        const reviewRequest = new RB.ReviewRequest({
            localSitePrefix: repository.get('localSitePrefix')
        });

        // TODO: handle errors
        await reviewRequest.save();
        RB.navigateTo(reviewRequest.get('reviewURL'));
    },
});


/**
 * The view for creating new review requests.
 *
 * This orchestrates several other objects to guide users through creating file
 * attachment only, pre-commit, or post-commit review requests.
 */
RB.NewReviewRequestView = RB.PageView.extend({
    el: '#new-review-request',

    template: _.template(dedent`
        <div class="rb-c-new-review-request">
         <div class="rb-c-sidebar -no-icons"></div>
         <div class="rb-c-new-review-request__repo-pane">
          <a href="#" class="rb-c-new-review-request__show-repositories">
           <span class="fa fa-chevron-left"></span>
           <%- repositoriesLabel %>
          </a>
          <div class="rb-c-new-review-request__repo-detail">
           <div class="rb-c-new-review-request__main">
            <div class="rb-c-new-review-request__hint"><%- hint %></div>
           </div>
          </div>
         </div>
        </div>
    `),

    events: {
        'click .rb-c-new-review-request__show-repositories':
            '_onShowRepositoriesClicked',
    },

    /**
     * Render the page.
     */
    renderPage() {
        /* Build the main UI for the page. */
        this.$pageContent.html(this.template({
            hint: gettext('Select a repository'),
            repositoriesLabel: gettext('Repositories'),
        }));

        this._$newReviewRequestContainer = this.$pageContent.find(
            '.rb-c-new-review-request');
        this._$repoPane = this.$pageContent.find(
            '.rb-c-new-review-request__repo-pane');
        this._$repoDetailContainer = this._$repoPane.find(
            '.rb-c-new-review-request__repo-detail');
        this._$repoSelectorContainer = this._$newReviewRequestContainer.find(
            '.rb-c-sidebar');
        this._$content = this._$repoDetailContainer.find(
            '.rb-c-new-review-request__main');
        this._$hint = this._$repoDetailContainer.find(
            '.rb-c-new-review-request__hint');

        /*
         * Add the repository selector. This will live either in the page's
         * sidebar (in desktop mode) or in the page's container (in mobile
         * mode).
         */
        this._repositorySelectionView = new RB.RepositorySelectionView({
            collection: this.model.get('repositories'),
        });
        this._repositorySelectionView.render();

        this.listenTo(this._repositorySelectionView,
                      'selected',
                      repository => this.model.set('repository', repository));
        this.listenTo(this.model, 'change:repository',
                      this._onRepositoryChanged);

        if (this._preCommitView) {
            this._$hint.hide();
            this._$content.append(this._preCommitView.render().el);
        }
        if (this._postCommitView) {
            this._$hint.hide();
            this._$content.append(this._postCommitView.render().el);
        }

        /*
         * If the only two options are the "None - File attachments only"
         * pseudo-repository and one real one, pre-select the real one to speed
         * up the 80% case. Otherwise, we'll leave it at the "Select a
         * repository" screen.
         */
        const repositories = this.model.get('repositories').models;

        if (repositories.length === 2) {
            repositories[1].trigger('selected', repositories[1]);
        }

        return this;
    },

    /**
     * Handle mobile mode changes.
     *
     * This will update the parent of the repository selector. In desktop
     * mode, it will be placed in the sidebar. In mobile mode, it will be
     * placed in a container in this view, with its display managed by CSS.
     *
     * Args:
     *     inMobileMode (boolean):
     *         Whether the UI is now in mobile mode.
     */
    onMobileModeChanged(inMobileMode) {
        this._repositorySelectionView.$el
            .detach()
            .appendTo(inMobileMode
                      ? this._$repoSelectorContainer
                      : this.$mainSidebar);
    },

    /**
     * Callback for when the current repository has changed.
     *
     * If the "Files Only" entry is selected, this shows the special
     * FilesOnlyPreCommitView in the right-hand pane.
     *
     * If a repository that supports fetching committed revisions is selected,
     * this will show both the pre-commit and post-commit UIs stacked
     * vertically. If the repository only supports pre-commit, only the
     * pre-commit UI is shown.
     */
    _onRepositoryChanged() {
        const repository = this.model.get('repository');

        if (repository === null) {
            /*
             * A repository is no longer selected. The user either chose
             * the File Attachments Only entry or hit the "< Repositories"
             * link on mobile.
             *
             * If on mobile, we're going to add a small delay (slightly longer
             * than the animation time) before removing any views, so that
             * they don't disappear during animation.
             */
            this._$newReviewRequestContainer
                .removeClass('js-repository-selected');

            if (this.inMobileMode) {
                _.delay(this._removeCommitViews.bind(this), 400);
            } else {
                this._removeCommitViews();
            }
        } else {
            /*
             * The user has selected a repository. Begin placing new views
             * based on the repository's capabilities.
             */
            this._$newReviewRequestContainer
                .addClass('js-repository-selected');

            this._removeCommitViews();

            if (repository.get('filesOnly')) {
                this._preCommitView = new FilesOnlyPreCommitView({
                    model: new FilesOnlyPreCommitModel({
                        repository: repository
                    })
                });
            } else {
                this._preCommitView = new RB.PreCommitView({
                    model: new RB.UploadDiffModel({
                        repository: repository
                    })
                });

                if (repository.get('supportsPostCommit')) {
                    this._postCommitView = new RB.PostCommitView({
                        model: new RB.PostCommitModel({
                            repository: repository
                        }),
                        $scrollContainer: this._$content,
                    });
                }
            }

            this._$hint.hide();
            this._$content.append(this._preCommitView.render().el);

            if (this._postCommitView) {
                this._$content.append(this._postCommitView.render().el);
            }
        }
    },

    /**
     * Remove the pre- and post-commit views.
     *
     * This will remove the views from the DOM and null them out, allowing
     * them to be rebuilt.
     */
    _removeCommitViews() {
        if (this._preCommitView) {
            this._preCommitView.remove();
            this._preCommitView = null;
        }

        if (this._postCommitView) {
            this._postCommitView.remove();
            this._postCommitView = null;
        }
    },

    /**
     * Handler for when the mobile-only Show Repositories link is clicked.
     *
     * Sets the page to slide back to the sidebar listing repositories.
     */
    _onShowRepositoriesClicked() {
        this._repositorySelectionView.unselect();
    },
});


})();
